/*
 * pdf_crack.h
 *
 *  Created on: 31.05.2013
 *      Author: alex
 */

#ifndef PDF_CRACK_H_
#define PDF_CRACK_H_
//---- DEFINES -----
#define SUCCESS 0
#define FAILURE -1
#define DEBUG 0
#define FOUND 1
#define NOTFOUND -1
#define NOTCRACK 0
#define CRACK 1
#define RC4SC 1
#define AES128 2
#define AES256 3
#define NO_SUCCESS -1

//---- INCLUDES -----
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <signal.h>
#ifdef _WIN32
#include "stat.h"
#else
#include <sys/stat.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#ifdef _WIN32
#include "hopenssl/md5.h"
#include "hopenssl/rc4.h"
#include "hopenssl/sha.h"
#include "hopenssl/aes.h"
#else
#include "openssl_mac/md5.h"
#include "openssl_mac/rc4.h"
#include "openssl_mac/sha.h"
#include "openssl_mac/aes.h"
#endif

//--- VARIABLES ---
char inputFile[40];
unsigned char toEncrypt[33];
char lowOrder[5];
char *idValue1 = NULL;
unsigned char *toCrackO = NULL;
unsigned char *toCrackU = NULL;
unsigned char *keyData = NULL;
unsigned char *md5init = NULL;
unsigned char rc4encryptedO[33];
unsigned char rc4encryptedU[33];
unsigned char pwdUTrunc[33];
unsigned char userValidationSalt[8];
unsigned char ownerValidationSalt[8];
int maxPasswordLength = 32;
int minPasswordLength = 0;
int crackOwner = NOTCRACK;
int documentLength = 0;
const int MinLetter = 33;
const int MaxLetter = 126;
int currentPos = 0;
int currentLetter = 32;
int lengthMD5init = 0;
int encryptMetadata = 0;
int encryptAlgorithm = RC4SC;
unsigned char paddingMd5[] = { 0xFF, 0xFF, 0xFF, 0xFF, '\0'};
const char filterBegin[] = "<</Filter/Standard\0";
const char trailer[] = "trailer\0";
const char pdfeof[] = "%%EOF\0";
const char lengthField[] = "Length\0";
const char pdfBegin[]  = "%PDF\0";
const char encrMeta[] = "EncryptMetadata\0";
const char stdCF[] = "StdCF\0";
const char trueValue[] = "true\0";
const char falseValue[] = "false\0";
const char valueRC4[] = "V2\0";
const char valueAES128[] = "AESV2\0";
const char valueAES256[] = "AESV3\0";
unsigned int inputParse = 0;
unsigned int revision = 0;
unsigned int passwordLength = 0;
unsigned int version = 0;
unsigned int flags = 0;
int ownerPwdFound = NOTFOUND;
int userPwdFound = NOTFOUND;
time_t startTime = 0;
int semid;
int* ids;
struct sembuf lck, unlck;
int shmid;
unsigned char *pwdU;
unsigned char *pwdO;

//--- ARRAYS
static const unsigned char pdfStatic[33] = {(unsigned char) 0x28, (unsigned char) 0xBF, (unsigned char) 0x4E, (unsigned char) 0x5E,
                                (unsigned char) 0x4E, (unsigned char) 0x75, (unsigned char) 0x8A, (unsigned char) 0x41,
                                (unsigned char) 0x64, (unsigned char) 0x00, (unsigned char) 0x4E, (unsigned char) 0x56,
                                (unsigned char) 0xFF, (unsigned char) 0xFA, (unsigned char) 0x01, (unsigned char) 0x08,
                                (unsigned char) 0x2E, (unsigned char) 0x2E, (unsigned char) 0x00, (unsigned char) 0xB6,
                                (unsigned char) 0xD0, (unsigned char) 0x68, (unsigned char) 0x3E, (unsigned char) 0x80,
                                (unsigned char) 0x2F, (unsigned char) 0x0C, (unsigned char) 0xA9, (unsigned char) 0xFE,
                                (unsigned char) 0x64, (unsigned char) 0x53, (unsigned char) 0x69, (unsigned char) 0x7A, '\0'};

//--- PROTOTYPES ---
int parseInput(int argc, char *argv[]);
void createOwnerPasswordsR2(unsigned char *pwd, int position, int actual);
void createOwnerPasswordsR3(unsigned char *pwd, int position, int actual);
void createOwnerPasswordsR5(unsigned char *pwd, int position, int actual);
void createUserPasswordsR2(unsigned char* pwd, int position, int actual);
void createUserPasswordsR3(unsigned char* pwd, int position, int actual);
void createUserPasswordsR5(unsigned char* pwd, int position, int actual);
void pdfHashR2(unsigned char* pwd);
void pdfHashR3(unsigned char* pwd);
void pdfHashR5(unsigned char *pwd);
void pdfHashUserPwdR2(unsigned char *pwd);
void pdfHashUserPwdR3(unsigned char *pwd);
//void pdfHashUserPwdR3AES(unsigned char *pwd);
void pdfHashUserPwdR5(unsigned char *pwd);
void lowOrderValue();
int prepareMD5();
char hexToInt(char letter);
void buildWord(unsigned char *word, unsigned char *result);
void copy(unsigned char *dest, unsigned char *src, int length);
void putTogether(unsigned char *text, unsigned char *toPut, int start, int length);
int openPDF();
int parseFilter(char *input, unsigned int *position);
int parseTrailer(char *input, unsigned int *position);
int parseCryptFilter(char *input, unsigned int *position);
int parseStdCryptFilter(char *input, unsigned int *position);
unsigned char* readPassword(char *input, unsigned int *position);
int checkPassword(char* string, char* toCompare, int length);

#endif /* PDF_CRACK_H_ */
